﻿using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Rhino.Mocks;
using StockholmsStad.Web.UI.Class.Interfaces;
using StockholmsStad.Web.UI.Class.Model;
using StockholmsStad.Web.UI.Class.Utilities;
using StockholmsStad.Web.UI.UIServiceReference;
using Microsoft.VisualStudio.TestTools.UnitTesting.Web;

namespace StockholmsStad.Web.UI.Test
{
    /// <summary>
    ///This is a test class for LoginModelTest and is intended
    ///to contain all LoginModelTest Unit Tests
    ///</summary>
    [TestClass()]
    public class LoginModelTest
    {
        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext { get; set; }

        #region Additional test attributes

        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //

        #endregion

        /// <summary>
        ///A test for Logout
        ///</summary>
        [TestMethod()]
        public void LogoutTest()
        {
            ISession session = new DictionarySessionAdapter(new Dictionary<string, object>());
            var mocks = new MockRepository();
            var serviceFacade = mocks.StrictMock<IServiceFacade>();
            IHttpContextAdapter context = mocks.StrictMock<IHttpContextAdapter>();
            var target = new LoginModel(session, serviceFacade, context);
            User user = new User();
            Expect.Call(serviceFacade.Login("user", "pass")).Return(true);
            Expect.Call(serviceFacade.GetUser("user")).Return(user);
            Expect.Call(serviceFacade.GetBooking(user)).Return(new Booking());
            Expect.Call(context.IsAuthenticated()).Return(true);
            // Second call is logout
            Expect.Call(context.IsAuthenticated()).Return(false);
            mocks.ReplayAll();
            target.Login("user", "pass");
            Assert.IsTrue(target.IsLoggedIn);
            Assert.IsFalse(target.IsLoggedIn);
            mocks.VerifyAll();
        }

        /// <summary>
        ///A test for Login
        ///</summary>
        [TestMethod()]
        public void LoginTest()
        {
            var mocks = new MockRepository();
            ISession session = new DictionarySessionAdapter(new Dictionary<string, object>());
            var booking = new Booking();
            var serviceFacade = mocks.StrictMock<IServiceFacade>();
            IHttpContextAdapter context = mocks.StrictMock<IHttpContextAdapter>();
            var target = new LoginModel(session, serviceFacade, context);
            User user = new User();
            Expect.Call(context.IsAuthenticated()).Return(false);
            Expect.Call(serviceFacade.Login("user", "pass")).Return(true);
            Expect.Call(serviceFacade.GetUser("user")).Return(user);
            Expect.Call(serviceFacade.GetBooking(user)).Return(booking);
            Expect.Call(context.IsAuthenticated()).Return(true);
            mocks.ReplayAll();
            Assert.IsFalse(target.IsLoggedIn);
            target.Login("user", "pass");
            Assert.IsTrue(target.IsLoggedIn);
            Assert.AreEqual(target.Booking, booking);
            mocks.VerifyAll();
        }

        /// <summary>
        ///A test for LoginModel Constructor
        ///</summary>
        [TestMethod()]
        public void LoginModelConstructorTest()
        {
            ISession session = new DictionarySessionAdapter(new Dictionary<string, object>());
            var mocks = new MockRepository();
            var serviceFacade = mocks.StrictMock<IServiceFacade>();
            IHttpContextAdapter context = mocks.StrictMock<IHttpContextAdapter>();
            Expect.Call(context.IsAuthenticated()).Return(false);
            mocks.ReplayAll();
            var target = new LoginModel(session, serviceFacade, context);
            Assert.IsNotNull(target);
            Assert.IsFalse(target.IsLoggedIn);
            mocks.VerifyAll();
        }

        /// <summary>
        ///A test for IsLoggedIn.
        ///</summary>
        [TestMethod()]
        public void IsLoggedInTest()
        {
            ISession session = new DictionarySessionAdapter(new Dictionary<string, object>());
            MockRepository mocks = new MockRepository();
            IHttpContextAdapter context = mocks.StrictMock<IHttpContextAdapter>();
            var serviceFacade = mocks.StrictMock<IServiceFacade>();
            // 1. no user
            Expect.Call(context.IsAuthenticated()).Return(false);
            mocks.ReplayAll();
            var target = new LoginModel(session, serviceFacade, context);
            Assert.IsFalse(target.IsLoggedIn);
            mocks.VerifyAll();
        }

        /// <summary>
        ///A test for IsLoggedIn.
        ///</summary>
        [TestMethod()]
        public void IsLoggedInTest2()
        {
            ISession session = new DictionarySessionAdapter(new Dictionary<string, object>());
            MockRepository mocks = new MockRepository();
            IHttpContextAdapter context = mocks.StrictMock<IHttpContextAdapter>();
            var serviceFacade = mocks.StrictMock<IServiceFacade>();           
            Expect.Call(context.IsAuthenticated()).Return(true);
            mocks.ReplayAll();
            var target = new LoginModel(session, serviceFacade, context);
            target.User = null;
            Assert.IsTrue(target.IsLoggedIn);
            mocks.VerifyAll();
        }


        /// <summary>
        ///A test for HasUnconfirmedBooking
        ///</summary>
        [TestMethod()]
        public void HasUnconfirmedBookingTest()
        {
            ISession session = new DictionarySessionAdapter(new Dictionary<string, object>());
            MockRepository mocks = new MockRepository();
            IHttpContextAdapter context = mocks.StrictMock<IHttpContextAdapter>();
            var serviceFacade = mocks.StrictMock<IServiceFacade>();
            LoginModel target = new LoginModel(session, serviceFacade, context);
            mocks.ReplayAll();
            Assert.IsFalse(target.HasUnconfirmedBooking);
            mocks.VerifyAll();
        }

        /// <summary>
        ///A test for HasUnconfirmedBooking
        ///</summary>
        [TestMethod()]
        public void HasUnconfirmedBookingTest2()
        {
            ISession session = new DictionarySessionAdapter(new Dictionary<string, object>());
            MockRepository mocks = new MockRepository();
            IHttpContextAdapter context = mocks.StrictMock<IHttpContextAdapter>();
            var serviceFacade = mocks.StrictMock<IServiceFacade>();
            LoginModel target = new LoginModel(session, serviceFacade, context);
            mocks.ReplayAll();
            target.Booking = new Booking();
            Assert.IsFalse(target.HasUnconfirmedBooking);
            mocks.VerifyAll();
        }

        /// <summary>
        ///A test for HasUnconfirmedBooking
        ///</summary>
        [TestMethod()]
        public void HasUnconfirmedBookingTest3()
        {
            ISession session = new DictionarySessionAdapter(new Dictionary<string, object>());
            MockRepository mocks = new MockRepository();
            IHttpContextAdapter context = mocks.StrictMock<IHttpContextAdapter>();
            var serviceFacade = mocks.StrictMock<IServiceFacade>();
            LoginModel target = new LoginModel(session, serviceFacade, context);
            mocks.ReplayAll();
            Booking booking = new Booking();
            booking.BookingMadeBeforeLogin = true;
            target.Booking = booking;
            Assert.IsTrue(target.HasUnconfirmedBooking);
            mocks.VerifyAll();
        }

        /// <summary>
        ///A test for User.
        /// No user
        ///</summary>
        [TestMethod()]
        public void UserTest()
        {
            ISession session = new DictionarySessionAdapter(new Dictionary<string, object>());
            MockRepository mocks = new MockRepository();
            IHttpContextAdapter context = mocks.StrictMock<IHttpContextAdapter>();
            var serviceFacade = mocks.StrictMock<IServiceFacade>();
            LoginModel target = new LoginModel(session, serviceFacade, context);
            Expect.Call(context.IsAuthenticated()).Return(false);
            mocks.ReplayAll();
            User actual;
            target.User = new User(){CoupleId = 42};
            actual = target.User;
            Assert.AreEqual(null, actual);
            mocks.VerifyAll();
        }
        /// <summary>
        ///A test for User.
        /// User is logged out
        ///</summary>
        [TestMethod()]
        public void UserTest2()
        {
            ISession session = new DictionarySessionAdapter(new Dictionary<string, object>());
            MockRepository mocks = new MockRepository();
            IHttpContextAdapter context = mocks.StrictMock<IHttpContextAdapter>();
            var serviceFacade = mocks.StrictMock<IServiceFacade>();
            LoginModel target = new LoginModel(session, serviceFacade, context);
            Expect.Call(context.IsAuthenticated()).Return(false);
            mocks.ReplayAll();
            User actual;
            User expected = new User() { CoupleId = 42 };
            target.User = expected;
            actual = target.User;
            Assert.AreEqual(null, actual);
            mocks.VerifyAll();
        }
        /// <summary>
        ///A test for User
        /// User is logged in, but session has timed out
        ///</summary>
        [TestMethod()]
        public void UserTest3()
        {
            ISession session = new DictionarySessionAdapter(new Dictionary<string, object>());
            MockRepository mocks = new MockRepository();
            IHttpContextAdapter context = mocks.StrictMock<IHttpContextAdapter>();
            var serviceFacade = mocks.StrictMock<IServiceFacade>();
            LoginModel target = new LoginModel(session, serviceFacade, context);
            Expect.Call(context.IsAuthenticated()).Return(true);
            Expect.Call(context.GetUsername()).Return("pelle");
            User user = new User() { CoupleId = 42 };
            Expect.Call(serviceFacade.GetUser("pelle")).Return(user);
            mocks.ReplayAll();
            User actual;
            target.User = null;
            actual = target.User;
            Assert.AreEqual(user, actual);
            mocks.VerifyAll();
        }
    }
}